home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / pickup.c < prev    next >
C/C++ Source or Header  |  1993-01-18  |  27KB  |  954 lines

  1. /*    SCCS Id: @(#)pickup.c    3.1    93/01/04    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  *    Contains code for picking objects up, and container use.
  7.  */
  8.  
  9. #include    "hack.h"
  10.  
  11. static void FDECL(unsplitobj, (struct obj *,struct obj *,long));
  12. static void FDECL(simple_look, (struct obj *,BOOLEAN_P));
  13. static boolean FDECL(query_classes, (char *,boolean *,boolean *,
  14.                  const char *,struct obj *,BOOLEAN_P,BOOLEAN_P));
  15. static boolean FDECL(pickup_object, (struct obj *,struct obj *));
  16. static boolean FDECL(mbag_explodes, (struct obj *,int));
  17. STATIC_PTR int FDECL(in_container,(struct obj *));
  18. STATIC_PTR int FDECL(ck_bag,(struct obj *));
  19. STATIC_PTR int FDECL(out_container,(struct obj *));
  20.  
  21. /*
  22.  *  How much the weight of the given container will change when the given
  23.  *  object is removed from it.  This calculation must match the one used
  24.  *  by weight() in mkobj.c.
  25.  */
  26. #define DELTA_CWT(cont,obj)        \
  27.     ((cont)->cursed ? (obj)->owt * 2 :    \
  28.               1 + ((obj)->owt / ((cont)->blessed ? 4 : 2)))
  29.  
  30. static const char moderateloadmsg[] = "You have a little trouble lifting";
  31. static const char nearloadmsg[] = "You have much trouble lifting";
  32.  
  33. static void
  34. unsplitobj(obj_block, obj_chip, resplit)
  35. register struct obj *obj_block, *obj_chip;
  36. long resplit;    /* non-zero => shift the quantities */
  37. {
  38.     if (obj_block->nobj != obj_chip) {
  39.         impossible("can't unsplit objects");
  40.     } else if (resplit) { /* 1st object should be reduced to 'resplit' */
  41.         obj_chip->quan += (obj_block->quan - resplit);
  42.         obj_block->quan = resplit;
  43.         obj_block->owt = weight(obj_block);
  44.         obj_chip->owt = weight(obj_chip);
  45.     } else {  /* 2nd obj should be merged back into 1st, then destroyed */
  46.         obj_block->nobj = obj_chip->nobj;
  47.         obj_block->nexthere = obj_chip->nexthere;
  48.         obj_block->quan += obj_chip->quan;
  49.         obj_block->owt = weight(obj_block);
  50.         /* no need to worry about 'unsplitbill'; unsplit only occurs
  51.            when unable to pick something up, hence we're not dealing
  52.            with billable objects here (I hope!)
  53.          */
  54.         dealloc_obj(obj_chip);
  55.     }
  56. }
  57.  
  58. /* much simpler version of the look-here code; used by query_classes() */
  59. static void
  60. simple_look(otmp, here)
  61. struct obj *otmp;    /* list of objects */
  62. boolean here;        /* flag for type of obj list linkage */
  63. {
  64.     /* Neither of the first two cases is expected to happen, since
  65.      * we're only called after multiple classes of objects have been
  66.      * detected, hence multiple objects must be present.
  67.      */
  68.     if (!otmp) {
  69.         impossible("simple_look(NULL)");
  70.     } else if (!(here ? otmp->nexthere : otmp->nobj)) {
  71.         pline("%s", doname(otmp));
  72.     } else {
  73.         winid tmpwin = create_nhwindow(NHW_MENU);
  74.         putstr(tmpwin, 0, "");
  75.         do {
  76.         putstr(tmpwin, 0, doname(otmp));
  77.         otmp = here ? otmp->nexthere : otmp->nobj;
  78.         } while (otmp);
  79.         display_nhwindow(tmpwin, TRUE);
  80.         destroy_nhwindow(tmpwin);
  81.     }
  82. }
  83.  
  84. int
  85. collect_obj_classes(ilets, otmp, here, incl_gold)
  86. char ilets[];
  87. register struct obj *otmp;
  88. boolean here, incl_gold;
  89. {
  90.     register int iletct = 0;
  91.     register char c, last_c = '\0';
  92.  
  93.     if (incl_gold)
  94.         ilets[iletct++] = def_oc_syms[GOLD_CLASS];
  95.     ilets[iletct] = '\0'; /* terminate ilets so that index() will work */
  96.     while (otmp) {
  97.         c = def_oc_syms[(int)otmp->oclass];
  98.         if (c != last_c && !index(ilets, (last_c = c)))
  99.             ilets[iletct++] = c,  ilets[iletct] = '\0';
  100.         otmp = here ? otmp->nexthere : otmp->nobj;
  101.     }
  102.  
  103.     return iletct;
  104. }
  105.  
  106. static boolean
  107. query_classes(olets, one_at_a_time, everything, action, objs, here, incl_gold)
  108. char olets[];
  109. boolean *one_at_a_time, *everything;
  110. const char *action;
  111. struct obj *objs;
  112. boolean here, incl_gold;
  113. {
  114.     char ilets[20], inbuf[BUFSZ];
  115.     int iletct, oletct;
  116.     char qbuf[QBUFSZ];
  117.  
  118.     olets[oletct = 0] = '\0';
  119.     *one_at_a_time = *everything = FALSE;
  120.     iletct = collect_obj_classes(ilets, objs, here, incl_gold);
  121.     if (iletct == 0) {
  122.         return FALSE;
  123.     } else if (iletct == 1) {
  124.         olets[0] = def_char_to_objclass(ilets[0]);
  125.         olets[1] = '\0';
  126.     } else  {    /* more than one choice available */
  127.         const char *where = 0;
  128.         register char sym, oc_of_sym, *p;
  129.         /* additional choices */
  130.         ilets[iletct++] = ' ';
  131.         ilets[iletct++] = 'a';
  132.         ilets[iletct++] = 'A';
  133.         ilets[iletct++] = (objs == invent ? 'i' : ':');
  134.         ilets[iletct] = '\0';
  135. ask_again:
  136.         olets[oletct = 0] = '\0';
  137.         *one_at_a_time = *everything = FALSE;
  138.         Sprintf(qbuf,"What kinds of thing do you want to %s? [%s]",
  139.             action, ilets);
  140.         getlin(qbuf,inbuf);
  141.         if (*inbuf == '\033') {
  142.             clear_nhwindow(WIN_MESSAGE);
  143.             return FALSE;
  144.         }
  145.         for (p = inbuf; (sym = *p++); ) {
  146.             /* new A function (selective all) added by GAN 01/09/87 */
  147.             if (sym == ' ') continue;
  148.             else if (sym == 'A') *one_at_a_time = TRUE;
  149.             else if (sym == 'a') *everything = TRUE;
  150.             else if (sym == ':') {
  151.             simple_look(objs, here);  /* dumb if objs==invent */
  152.             goto ask_again;
  153.             } else if (sym == 'i') {
  154.             (void) display_inventory(NULL, FALSE);
  155.             goto ask_again;
  156.             } else {
  157.             oc_of_sym = def_char_to_objclass(sym);
  158.             if (index(ilets,sym)) {
  159.                 olets[oletct++] = oc_of_sym;
  160.                 olets[oletct] = '\0';
  161.             } else {
  162.                 if (!where)
  163.                 where = !strcmp(action,"pick up")  ? "here" :
  164.                     !strcmp(action,"take out") ?
  165.                                 "inside" : "";
  166.                 if (*where)
  167.                 pline("There are no %c's %s.", sym, where);
  168.                 else
  169.                 You("have no %c's.", sym);
  170.             }
  171.             }
  172.         }
  173.         if (!oletct && !*everything) *one_at_a_time = TRUE;
  174.     }
  175.     return TRUE;
  176. }
  177.  
  178. void
  179. pickup(all)
  180. int all;    /* all >= 0 => yes/no; < 0 => -count */
  181. {
  182.     register struct obj *obj;
  183.     struct obj *obj2, *objx;
  184.     boolean all_of_a_type = FALSE, selective = FALSE;
  185.     char olets[20];
  186.     long count;
  187.  
  188.     count = (all < 0) ? (-1L * all) : 0L;
  189.     if (count) all = 0;
  190.  
  191.     if(Levitation && !Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz)) {
  192.         if ((multi && !flags.run) || (all && !flags.pickup))
  193.             read_engr_at(u.ux,u.uy);
  194.         return;
  195.     }
  196.  
  197.     /* multi && !flags.run means they are in the middle of some other
  198.      * action, or possibly paralyzed, sleeping, etc.... and they just
  199.      * teleported onto the object.  They shouldn't pick it up.
  200.      */
  201.     if ((multi && !flags.run) || (all && !flags.pickup)) {
  202.         int ct = 0;
  203.  
  204.         for (obj = level.objects[u.ux][u.uy]; obj;
  205.                          obj = obj->nexthere)
  206.             if(obj != uchain)
  207.                 ct++;
  208.  
  209.         /* If there are objects here, take a look.
  210.          */
  211.         if (ct) {
  212.             if (flags.run)
  213.                 nomul(0);
  214.             flush_screen(1);
  215.             if (ct < 5)
  216.                 (void) dolook();
  217.             else {
  218.                 read_engr_at(u.ux,u.uy);
  219.                 pline("There are several objects here.");
  220.             }
  221.         } else read_engr_at(u.ux,u.uy);
  222.         return;
  223.     }
  224.  
  225.     /* check for more than one object */
  226.     if(!all) {
  227.         register int ct = 0;
  228.  
  229.         for(obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere)
  230.             ct++;
  231.         if(ct < 2)
  232.             all++;
  233.         else {
  234.             pline("There are several objects here.");
  235.             count = 0;
  236.         }
  237.     }
  238.  
  239. #ifdef POLYSELF
  240.     if (nolimbs(uasmon)) {
  241.         You("cannot pick things up without limbs.");
  242.         return;
  243.     }
  244. #endif
  245.  
  246.     /* added by GAN 10/24/86 to allow selective picking up */
  247.     if (!all) {
  248.         if (!query_classes(olets, &selective, &all_of_a_type,
  249.               "pick up", level.objects[u.ux][u.uy], TRUE, FALSE))
  250.             return;
  251.     }
  252.     if(all_of_a_type && !olets[0]) all = TRUE;
  253.  
  254.     for(obj = level.objects[u.ux][u.uy]; obj; obj = obj2) {
  255.         obj2 = obj->nexthere;    /* perhaps obj will be picked up */
  256.         objx = 0;
  257.         if(flags.run) nomul(0);
  258.  
  259.         if(!all)  {
  260.             if(!selective && !index(olets,obj->oclass)) continue;
  261.  
  262.             if (!all_of_a_type) {
  263.             char qbuf[QBUFSZ];
  264.             Sprintf(qbuf,"Pick up %s?", doname(obj));
  265.             switch ((obj->quan < 2L) ? ynaq(qbuf) : ynNaq(qbuf)) {
  266.             case 'q': return;
  267.             case 'n': continue;
  268.             case 'a':
  269.                 all_of_a_type = TRUE;
  270.                 if (selective) {
  271.                 selective = FALSE;
  272.                 olets[0] = obj->oclass;
  273.                 olets[1] = '\0';
  274.                 }
  275.                 break;
  276.             case '#':    /* count was entered */
  277.                 if (!yn_number) continue; /* 0 count => No */
  278.                 else count = yn_number;
  279.                 /* fall thru :-} */
  280.             default:    /* 'y' */
  281.                 break;
  282.             }
  283.             }
  284.         }
  285.  
  286.         if (count) {
  287.             /* Pickup a specific number of items; split the object
  288.                unless count corresponds to full quantity.  1 special
  289.                case:  cursed loadstones will remain as merged unit.
  290.              */
  291.             if (count < obj->quan &&
  292.                 (!obj->cursed || obj->otyp != LOADSTONE)) {
  293.             objx = splitobj(obj, count);
  294.             if (!objx || objx->nexthere != obj2)
  295.                 impossible("bad object split in pickup");
  296.             }
  297.             count = 0;    /* reset */
  298.         }
  299.         if (pickup_object(obj, objx)) break;
  300.     }
  301.  
  302.     /*
  303.      *  Re-map what is at the hero's location after the pickup so the
  304.      *  map is correct.
  305.      */
  306.     newsym(u.ux,u.uy);
  307. }
  308.  
  309. /*
  310.  * Pick up an object from the ground or out of a container and add it to
  311.  * the inventory.  Returns true if pickup() should break out of its loop.
  312.  */
  313. static boolean
  314. pickup_object(obj, objx)
  315. struct obj *obj, *objx;
  316. {
  317.     int wt, nearload;
  318.     long pickquan;
  319.  
  320.     if (obj == uchain) {    /* do not pick up attached chain */
  321.         return FALSE;
  322.     } else if (obj->oartifact && !touch_artifact(obj,&youmonst)) {
  323.         return FALSE;
  324.     } else if (obj->otyp == GOLD_PIECE) {
  325.         /*
  326.          *  Special consideration for gold pieces...
  327.          */
  328.         long iw = (long)max_capacity() - ((u.ugold + 50L) / 100L);
  329.         long gold_capacity = ((-iw) * 100L) - 50L + 99L - u.ugold;
  330.  
  331.         if (gold_capacity <= 0L) {
  332.         if (objx) unsplitobj(obj, objx, 0L);
  333.        pline("There %s %ld gold piece%s here, but you cannot carry any more.",
  334.             (obj->quan == 1L) ? "is" : "are",
  335.             obj->quan, plur(obj->quan));
  336.         return FALSE;
  337.         } else if (gold_capacity < obj->quan) {
  338.         if (objx) unsplitobj(obj, objx, 0L);
  339.         You("can only carry %s of the %ld gold pieces lying here.",
  340.             gold_capacity == 1L ? "one" : "some", obj->quan);
  341.         pline("%s %ld gold piece%s.",
  342.             nearloadmsg, gold_capacity, plur(gold_capacity));
  343.         u.ugold += gold_capacity;
  344.         obj->quan -= gold_capacity;
  345.         costly_gold(obj->ox, obj->oy, gold_capacity);
  346.         } else {
  347.         u.ugold += obj->quan;
  348.         if ((nearload = near_capacity()) != 0)
  349.             pline("%s %ld gold piece%s.",
  350.               nearload < MOD_ENCUMBER ?
  351.               moderateloadmsg : nearloadmsg,
  352.               obj->quan, plur(obj->quan));
  353.         else
  354.             prinv(NULL, obj, 0L);
  355.         costly_gold(obj->ox, obj->oy, obj->quan);
  356.         delobj(obj);
  357.         }
  358.         flags.botl = 1;
  359.         if (flags.run) nomul(0);
  360.         return FALSE;
  361.     } else if (obj->otyp == CORPSE) {
  362.  
  363.         if (obj->corpsenm == PM_COCKATRICE && !uarmg
  364. #ifdef POLYSELF
  365.         && !resists_ston(uasmon)
  366. #endif
  367.         ) {
  368. #ifdef POLYSELF
  369.         if (poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM))
  370.             display_nhwindow(WIN_MESSAGE, FALSE);
  371.         else
  372. #endif
  373.         {
  374.           pline("Touching the cockatrice corpse is a fatal mistake.");
  375.             You("turn to stone.");
  376.             You("die...");
  377.             killer_format = KILLED_BY_AN;
  378.             killer = "cockatrice corpse";
  379.             done(STONING);
  380.         }
  381.         } else if (is_rider(&mons[obj->corpsenm])) {
  382.         pline("At your touch, the corpse suddenly moves...");
  383.         revive_corpse(obj, 1, FALSE);
  384.         exercise(A_WIS, FALSE);
  385.         return FALSE;
  386.         }
  387.  
  388.     } else  if (obj->otyp == SCR_SCARE_MONSTER) {
  389.         if (obj->blessed) obj->blessed = 0;
  390.         else if (!obj->spe && !obj->cursed) obj->spe = 1;
  391.         else {
  392.         pline("The scroll%s turn%s to dust as you pick %s up.",
  393.             plur(obj->quan), (obj->quan == 1L) ? "s" : "",
  394.             (obj->quan == 1L) ? "it" : "them");
  395.         if (!(objects[SCR_SCARE_MONSTER].oc_name_known) &&
  396.                     !(objects[SCR_SCARE_MONSTER].oc_uname))
  397.             docall(obj);
  398.         useupf(obj);
  399.         return FALSE;
  400.         }
  401.     }
  402.  
  403.     wt = max_capacity() + (int)obj->owt;
  404.     if (obj->otyp == LOADSTONE)
  405.         goto lift_some;     /* pick it up even if too heavy */
  406. #ifdef POLYSELF
  407.     if (obj->otyp == BOULDER && throws_rocks(uasmon)) {
  408.         goto lift_some;
  409.     }
  410. #endif
  411.     if (wt > 0) {
  412.         if (obj->quan > 1L) {
  413.         /* see how many we can lift */
  414.         long qq, savequan = obj->quan;
  415.         int iw = max_capacity();
  416.         /*  This is correct only because containers */
  417.         /*  don't merge.    -dean            */
  418.         for (qq = 1; qq < savequan; qq++) {
  419.             obj->quan = qq;
  420.             if (iw + weight(obj) > 0)
  421.                 break;
  422.         }
  423.         obj->quan = savequan;
  424.         qq--;
  425.         /* we can carry qq of them */
  426.         if (qq) {
  427.             if (objx) {        /* temporarily unsplit */
  428.             savequan = obj->quan;
  429.             obj->quan += objx->quan;
  430.             }
  431.             You("can only carry %s of the %s lying here.",
  432.             (qq == 1L) ? "one" : "some", doname(obj));
  433.             if (objx) {        /* re-do the prior split */
  434.             obj->quan = savequan;
  435.             unsplitobj(obj, objx, qq);
  436.             } else {        /* split into two groups */
  437.             objx = splitobj(obj, qq);
  438.             if (objx->otyp == SCR_SCARE_MONSTER) objx->spe = 0;
  439.             }
  440.             goto lift_some;
  441.         }
  442.         }
  443.         if (objx) unsplitobj(obj, objx, 0L);
  444.         pline("There %s %s here, but %s.",
  445.             (obj->quan == 1L) ? "is" : "are", doname(obj),
  446.             !invent ? (obj->quan == 1L ?
  447.                 "it is too heavy for you to lift" :
  448.                 "they are too heavy for you to lift") :
  449.             "you cannot carry any more");
  450.         if (obj->otyp == SCR_SCARE_MONSTER) obj->spe = 0;
  451.         return TRUE;
  452.     }
  453.  
  454. lift_some:
  455.     if (inv_cnt() >= 52) {
  456.         if (objx) unsplitobj(obj, objx, 0L);
  457.         Your("knapsack cannot accommodate any more items.");
  458.         if (obj->otyp == SCR_SCARE_MONSTER) obj->spe = 0;
  459.         return TRUE;
  460.     }
  461.  
  462.     pickquan = obj->quan;    /* save number picked up */
  463.     obj = pick_obj(obj);
  464.  
  465.     if (!Blind) obj->dknown = 1;
  466.     if (uwep && uwep == obj) mrg_to_wielded = TRUE;
  467.     nearload = near_capacity();
  468.     prinv(nearload > SLT_ENCUMBER ? nearloadmsg :
  469.           nearload > UNENCUMBERED ? moderateloadmsg : NULL,
  470.           obj, pickquan);
  471.     mrg_to_wielded = FALSE;
  472.     return FALSE;
  473. }
  474.  
  475. /* Gold never reaches this routine. */
  476. struct obj *
  477. pick_obj(otmp)
  478. register struct obj *otmp;
  479. {
  480.     freeobj(otmp);
  481.     if (*u.ushops && costly_spot(u.ux, u.uy) &&
  482.         otmp != uball)     /* don't charge for this - kd, 1/17/90 */
  483.        /* sets obj->unpaid if necessary */
  484.         addtobill(otmp, TRUE, FALSE, FALSE);
  485.     if(Invisible) newsym(u.ux,u.uy);
  486.     return(addinv(otmp));    /* might merge it with other objects */
  487. }
  488.  
  489. /*
  490.  * prints a message if encumbrance changed since the last check and
  491.  * returns the new encumbrance value (from near_capacity()).
  492.  */
  493. int
  494. encumber_msg()
  495. {
  496.     static int oldcap = UNENCUMBERED;
  497.     int newcap = near_capacity();
  498.  
  499.     if(oldcap < newcap) {
  500.     switch(newcap) {
  501.     case 1: Your("movements are slowed slightly because of your load.");
  502.         break;
  503.     case 2: You("rebalance your load.  Movement is difficult.");
  504.         break;
  505.     case 3: You("stagger under your heavy load.  Movement is very hard.");
  506.         break;
  507.     default: You("can barely move a handspan with this load!");
  508.         break;
  509.     }
  510.     flags.botl = 1;
  511.     } else if(oldcap > newcap) {
  512.     switch(newcap) {
  513.     case 0: Your("movements are now unencumbered.");
  514.         break;
  515.     case 1: Your("movements are only slowed slightly by your load.");
  516.         break;
  517.     case 2: You("rebalance your load.  Movement is still difficult.");
  518.         break;
  519.     case 3: You("stagger under your load.  Movement is still very hard.");
  520.         break;
  521.     }
  522.     flags.botl = 1;
  523.     }
  524.  
  525.     oldcap = newcap;
  526.     return (newcap);
  527. }
  528.  
  529. int
  530. doloot()    /* loot a container on the floor. */
  531. {
  532.     register struct obj *cobj, *nobj;
  533.     register int c;
  534.     int timepassed = 0;
  535.  
  536.     if (Levitation && !Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz)) {
  537.         You("cannot reach the floor.");
  538.         return(0);
  539.     }
  540.     if(is_pool(u.ux, u.uy)) {
  541.         You("cannot loot things that are deep in the water.");
  542.         return(0);
  543.     }
  544.  
  545. #ifdef POLYSELF
  546.     if(nolimbs(uasmon)) {
  547.         You("cannot loot things without limbs.");
  548.         return(0);
  549.     }
  550. #endif
  551.  
  552.     for(cobj = level.objects[u.ux][u.uy]; cobj; cobj = nobj) {
  553.         nobj = cobj->nexthere;
  554.  
  555.         if(Is_container(cobj)) {
  556.             char qbuf[QBUFSZ];
  557.  
  558.             Sprintf(qbuf, "There is %s here, loot it?", doname(cobj));
  559.             c = ynq(qbuf);
  560.             if(c == 'q') return (timepassed);
  561.             if(c == 'n') continue;
  562.  
  563.             if(cobj->olocked) {
  564.             pline("Hmmm, it seems to be locked.");
  565.             continue;
  566.             }
  567.             if(cobj->otyp == BAG_OF_TRICKS) {
  568.             You("carefully open the bag...");
  569.             pline("It develops a huge set of teeth and bites you!");
  570.             c = rnd(10);
  571.             if(Half_physical_damage) c = (c+1) / 2;
  572.             losehp(c, "carnivorous bag", KILLED_BY_AN);
  573.             makeknown(BAG_OF_TRICKS);
  574.             timepassed = 1;
  575.             continue;
  576.             }
  577.  
  578.             You("carefully open %s...", the(xname(cobj)));
  579.             if (cobj->otrapped && chest_trap(cobj, FINGER, FALSE)) {
  580.             timepassed = 1;
  581.             continue;    /* explosion destroyed cobj */
  582.             }
  583.             if(multi < 0) return (1); /* a paralysis trap */
  584.  
  585.             timepassed |= use_container(cobj, 0);
  586.         }
  587.     }
  588.     return (timepassed);
  589. }
  590.  
  591. /*
  592.  * Decide whether an object being placed into a magic bag will cause
  593.  * it to explode.  If the object is a bag itself, check recursively.
  594.  */
  595. static boolean
  596. mbag_explodes(obj, depthin)
  597.     struct obj *obj;
  598.     int depthin;
  599. {
  600.     /* odds: 1/1, 2/2, 3/4, 4/8, 5/16, 6/32, 7/64, 8/128, 9/128, 10/128,... */
  601.     if ((Is_mbag(obj) || (obj->otyp == WAN_CANCELLATION && obj->spe > 0)) &&
  602.     (rn2(1 << (depthin > 7 ? 7 : depthin)) <= depthin))
  603.     return TRUE;
  604.     else if (Is_container(obj)) {
  605.     struct obj *otmp;
  606.  
  607.     for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
  608.         if (mbag_explodes(otmp, depthin+1)) return TRUE;
  609.     }
  610.     return FALSE;
  611. }
  612.  
  613. /* A variable set in use_container(), to be used by the callback routines */
  614. /* chk_bg(), in_container(), and out_container() from askchain().      */
  615. static struct obj NEARDATA *current_container;
  616. #define Icebox (current_container->otyp == ICE_BOX)
  617.  
  618. STATIC_PTR int
  619. in_container(obj)
  620. register struct obj *obj;
  621. {
  622.     register struct obj *gold;
  623.     boolean is_gold = (obj->otyp == GOLD_PIECE);
  624.     boolean floor_container = !carried(current_container);
  625.     char buf[BUFSZ];
  626.  
  627.     if (!current_container) {
  628.         impossible("<in> no current_container?");
  629.         return 0;
  630.     } else if (obj == uball || obj == uchain) {
  631.         You("must be kidding.");
  632.         return 0;
  633.     } else if (obj == current_container) {
  634.         pline("That would be an interesting topological exercise.");
  635.         return 0;
  636.     } else if (obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) {
  637.         Norep("You cannot %s something you are wearing.",
  638.             Icebox ? "refrigerate" : "stash");
  639.         return 0;
  640.     } else if ((obj->otyp == LOADSTONE) && obj->cursed) {
  641.         obj->bknown = 1;
  642.           pline("The stone%s won't leave your person.", plur(obj->quan));
  643.         return 0;
  644.     } else if (obj->otyp == AMULET_OF_YENDOR ||
  645.            obj->otyp == CANDELABRUM_OF_INVOCATION ||
  646.            obj->otyp == BELL_OF_OPENING ||
  647.            obj->otyp == SPE_BOOK_OF_THE_DEAD) {
  648.     /* Prohibit Amulets in containers; if you allow it, monsters can't
  649.      * steal them.  It also becomes a pain to check to see if someone
  650.      * has the Amulet.  Ditto for the Candelabrum, the Bell and the Book.
  651.      */
  652.         pline("%s cannot be confined in such trappings.", The(xname(obj)));
  653.         return 0;
  654.     }
  655. #ifdef WALKIES
  656.     else if (obj->otyp == LEASH && obj->leashmon != 0) {
  657.         pline("%s is attached to your pet.", The(xname(obj)));
  658.         return 0;
  659.     }
  660. #endif
  661.     else if (obj == uwep) {
  662.         if (welded(obj)) {
  663.             weldmsg(obj, FALSE);
  664.             return 0;
  665.         }
  666.         setuwep((struct obj *) 0);
  667.         if (uwep) return 0;    /* unwielded, died, rewielded */
  668.     }
  669.  
  670.     /* boxes can't fit into any container */
  671.     if (obj->otyp == ICE_BOX || Is_box(obj)) {
  672.         /*
  673.          *  xname() uses a static result array.  Save obj's name
  674.          *  before current_container's name is computed.  Don't
  675.          *  use the result of strcpy() within You() --- the order
  676.          *  of evaluation of the parameters is undefined.
  677.          */
  678.         Strcpy(buf, the(xname(obj)));
  679.         You("cannot fit %s into %s.", buf,
  680.             the(xname(current_container)));
  681.         return 0;
  682.     }
  683.  
  684.     freeinv(obj);
  685.  
  686.     if (is_gold) {    /* look for other gold within the container */
  687.         for (gold = current_container->cobj; gold; gold = gold->nobj)
  688.             if (gold->otyp == GOLD_PIECE) break;
  689.     } else
  690.         gold = 0;
  691.  
  692.     if (gold) {
  693.         gold->quan += obj->quan;
  694.     } else {
  695.         obj->nobj = current_container->cobj;
  696.         current_container->cobj = obj;
  697.     }
  698.  
  699.     current_container->owt = weight(current_container);
  700.  
  701.     Strcpy(buf, the(xname(current_container)));
  702.     You("put %s into %s.", doname(obj), buf);
  703.  
  704.     if (floor_container && costly_spot(u.ux, u.uy)) {
  705.         sellobj_state(TRUE);
  706.         sellobj(obj, u.ux, u.uy);
  707.         sellobj_state(FALSE);
  708.     }
  709.     (void) snuff_candle(obj); /* must follow the "put" msg */
  710.     if (Icebox && obj->otyp != OIL_LAMP && obj->otyp != BRASS_LANTERN
  711.             && !Is_candle(obj))
  712.         obj->age = monstermoves - obj->age; /* actual age */
  713.  
  714.     else if (Is_mbag(current_container) && mbag_explodes(obj, 0)) {
  715.         You("are blasted by a magical explosion!");
  716.  
  717.         /* the !floor_container case is taken care of */
  718.         if(*u.ushops && costly_spot(u.ux, u.uy) && floor_container) {
  719.             register struct monst *shkp;
  720.  
  721.             if ((shkp = shop_keeper(*u.ushops)) != 0)
  722.             (void)stolen_value(current_container, u.ux, u.uy,
  723.                        (boolean)shkp->mpeaceful, FALSE);
  724.         }
  725.         delete_contents(current_container);
  726.         if (!floor_container)
  727.             useup(current_container);
  728.         else if (obj_here(current_container, u.ux, u.uy))
  729.             useupf(current_container);
  730.         else
  731.             panic("in_container:  bag not found.");
  732.  
  733.         losehp(d(6,6),"magical explosion", KILLED_BY_AN);
  734.         current_container = 0;    /* baggone = TRUE; */
  735.     }
  736.  
  737.     if (is_gold) {
  738.         if (gold) dealloc_obj(obj);
  739.         bot();    /* update character's gold piece count immediately */
  740.     }
  741.  
  742.     return(current_container ? 1 : -1);
  743. }
  744.  
  745. STATIC_PTR int
  746. ck_bag(obj)
  747. struct obj *obj;
  748. {
  749.     return current_container && obj != current_container;
  750. }
  751.  
  752. STATIC_PTR int
  753. out_container(obj)
  754. register struct obj *obj;
  755. {
  756.     register struct obj *otmp, *ootmp;
  757.     boolean is_gold = (obj->otyp == GOLD_PIECE);
  758.     int loadlev;
  759.     long quan;
  760.  
  761.     if (!current_container) {
  762.         impossible("<out> no current_container?");
  763.         return -1;
  764.     } else if (is_gold) {
  765.         obj->owt = weight(obj);
  766.     } else if (inv_cnt() >= 52) {
  767.         You("have no room to hold anything else.");
  768.         return -1;    /* skips gold too; oh well */
  769.     }
  770.  
  771.     if(obj->oartifact && !touch_artifact(obj,&youmonst)) return 0;
  772.  
  773.     if(obj->otyp != LOADSTONE && max_capacity() + (int)obj->owt -
  774.        (carried(current_container) ?
  775.         (current_container->otyp == BAG_OF_HOLDING ?
  776.          (int)DELTA_CWT(current_container,obj) : (int)obj->owt) : 0) > 0) {
  777.         char buf[BUFSZ];
  778.  
  779.         Strcpy(buf, doname(obj));
  780.         pline("There %s %s in %s, but %s.",
  781.             obj->quan==1 ? "is" : "are",
  782.             buf, the(xname(current_container)),
  783.             invent ? "you cannot carry any more"
  784.             : "it is too heavy for you to carry");
  785.         /* "too heavy for you to lift" is not right if you're carrying
  786.            the container... */
  787.         return(0);
  788.     }
  789.     /* Remove the object from the list. */
  790.     if (obj == current_container->cobj)
  791.         current_container->cobj = obj->nobj;
  792.     else {
  793.         for(otmp = current_container->cobj; otmp->nobj != obj;
  794.                                 otmp = otmp->nobj)
  795.             if(!otmp->nobj) panic("out_container");
  796.         otmp->nobj = obj->nobj;
  797.     }
  798.  
  799.     current_container->owt = weight(current_container);
  800.  
  801.     if (Icebox && obj->otyp != OIL_LAMP && obj->otyp != BRASS_LANTERN
  802.             && !Is_candle(obj))
  803.         obj->age = monstermoves - obj->age;
  804.     /* simulated point of time */
  805.  
  806.     if(!obj->unpaid && !carried(current_container) &&
  807.          costly_spot(current_container->ox, current_container->oy)) {
  808.  
  809.         addtobill(obj, FALSE, FALSE, FALSE);
  810.     }
  811.  
  812.     quan = obj->quan;
  813.     ootmp = addinv(obj);
  814.     loadlev = near_capacity();
  815.     prinv(loadlev ?
  816.           (loadlev < MOD_ENCUMBER ?
  817.            "You have a little trouble removing" :
  818.            "You have much trouble removing") : NULL,
  819.           ootmp, quan);
  820.  
  821.     if (is_gold) {
  822.         dealloc_obj(obj);
  823.         bot();    /* update character's gold piece count immediately */
  824.     }
  825.     return 1;
  826. }
  827.  
  828. /* for getobj: allow counts, allow all types, expect food */
  829. static const char NEARDATA frozen_food[] =
  830.     { ALLOW_COUNT, ALL_CLASSES, FOOD_CLASS, 0 };
  831.  
  832. int
  833. use_container(obj, held)
  834. register struct obj *obj;
  835. register int held;
  836. {
  837.     register int cnt = 0;
  838.     register struct obj *curr, *prev, *otmp;
  839.     boolean one_by_one, allflag;
  840.     char select[MAXOCLASSES+1];
  841.     char qbuf[QBUFSZ];
  842.     int used = 0, lcnt = 0;
  843.     long loss = 0L;
  844.     register struct monst *shkp;
  845.  
  846.     current_container = obj;    /* for use by in/out_container */
  847.     if (current_container->olocked) {
  848.         pline("%s seems to be locked.", The(xname(current_container)));
  849.         if (held) You("must put it down to unlock.");
  850.         return 0;
  851.     }
  852.     /* Count the number of contained objects. Sometimes toss objects if */
  853.     /* a cursed magic bag.                            */
  854.     for(curr = obj->cobj, prev = (struct obj *) 0; curr;
  855.                         prev = curr, curr = otmp) {
  856.         otmp = curr->nobj;
  857.         if (Is_mbag(obj) && obj->cursed && !rn2(13)) {
  858.         if (curr->known)
  859.             pline("%s to have vanished!", The(aobjnam(curr,"seem")));
  860.         else
  861.             You("%s %s disappear.", Blind ? "notice" : "see",
  862.                             doname(curr));
  863.         if (prev)
  864.             prev->nobj = otmp;
  865.         else
  866.             obj->cobj = otmp;
  867.  
  868.         if(*u.ushops && (shkp = shop_keeper(*u.ushops))) {
  869.             if(held) {
  870.             if(curr->unpaid)
  871.                 loss += stolen_value(curr, u.ux, u.uy,
  872.                          (boolean)shkp->mpeaceful, TRUE);
  873.             lcnt++;
  874.             } else if(costly_spot(u.ux, u.uy)) {
  875.             loss += stolen_value(curr, u.ux, u.uy,
  876.                          (boolean)shkp->mpeaceful, TRUE);
  877.             lcnt++;
  878.             }
  879.         }
  880.         /* obfree() will free all contained objects */
  881.         obfree(curr, (struct obj *) 0);
  882.         } else
  883.         cnt++;
  884.     }
  885.  
  886.     if (cnt && loss)
  887.         You("owe %ld zorkmids for lost item%s.",
  888.         loss, lcnt > 1 ? "s" : "");
  889.  
  890.     current_container->owt = weight(current_container);
  891.  
  892.     if(!cnt)
  893.         pline("%s %s is empty.", (held) ? "Your" : "The", xname(obj));
  894.     else {
  895.         Sprintf(qbuf, "Do you want to take something out of %s?",
  896.             the(xname(obj)));
  897. ask_again:
  898.         switch (yn_function(qbuf, ":ynq", 'n')) {
  899.         case ':':
  900.         container_contents(current_container, FALSE, FALSE);
  901.         goto ask_again;
  902.         case 'y':
  903.         if (query_classes(select, &one_by_one, &allflag, "take out",
  904.                    current_container->cobj, FALSE, FALSE)) {
  905.             if (askchain((struct obj **)¤t_container->cobj,
  906.                  (one_by_one ? (char *)0 : select), allflag,
  907.                  out_container, (int (*)())0, 0, "nodot"))
  908.             used = 1;
  909.         }
  910.         /*FALLTHRU*/
  911.         case 'n':
  912.         break;
  913.         case 'q':
  914.         default:
  915.         return 0;
  916.         }
  917.     }
  918.  
  919.     if (!invent && (u.ugold == 0 || Icebox)) return used;
  920.     if (yn_function("Do you wish to put something in?", ynqchars, 'n')
  921.         != 'y') return used;
  922.     if (Icebox && current_container->dknown) {
  923.         otmp = getobj(frozen_food, "put in");
  924.         if(!otmp || !in_container(otmp))
  925.             flags.move = multi = 0;
  926.     } else {
  927.         if (query_classes(select, &one_by_one, &allflag, "put in",
  928.                        invent, FALSE, (u.ugold != 0L))) {
  929.             struct obj *u_gold = (struct obj *)0;
  930.             if (u.ugold && (one_by_one || (allflag && !*select)
  931.                     || index(select, GOLD_CLASS))) {
  932.             /* make gold object & insert at head of inventory */
  933.             u_gold = mkgoldobj(u.ugold);    /*(removes gold too)*/
  934.             u.ugold = u_gold->quan;        /* put the gold back */
  935.             u_gold->nobj = invent;
  936.             invent = u_gold;
  937.             }
  938.             used = (askchain((struct obj **)&invent,
  939.                 (one_by_one ? (char *)0 : select), allflag,
  940.                 in_container, ck_bag, 0, "nodot") > 0);
  941.             if (u_gold && invent && invent->otyp == GOLD_PIECE) {
  942.             /* didn't stash [all of] it */
  943.             u_gold = invent;
  944.             invent = u_gold->nobj;
  945.             dealloc_obj(u_gold);
  946.             }
  947.         }
  948.     }
  949.  
  950.     return used;
  951. }
  952.  
  953. /*pickup.c*/
  954.